package org.extframework.ld.xml;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.extframework.ld.bean.Power;
import org.extframework.ld.conf.PageType;
import org.extframework.ld.content.ExtContent;
import org.extframework.ld.content.XmlContent;
import org.extframework.ld.control.ExtJsonControl;
import org.extframework.ld.exception.SysException;
import org.extframework.ld.exception.WebException;
import org.extframework.ld.sort.RightMenuSort;
import org.extframework.ld.util.FileList;
import org.extframework.ld.util.FileUtil;
import org.extframework.ld.xml.base.DialogItem;
import org.extframework.ld.xml.base.DialogItems;
import org.extframework.ld.xml.base.DialogProperties;
import org.extframework.ld.xml.base.PageCustom;
import org.extframework.ld.xml.base.PageDataIndex;
import org.extframework.ld.xml.base.PageXml;
import org.extframework.ld.xml.base.RightMenu;
import org.extframework.ld.xml.base.component.ExtComboBox;
import org.extframework.ld.xml.base.component.ExtUpFileLoad;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

/**
 * @author : Dong.Li
 * @created : 2013-1-17
 * @version : 1.0
 * @description :
 */
public class ExtPageXmlControl {

	private String extPageDir = null;
	private String dialogPageDir = null;
	private String detailPageDir = null;

	private SAXBuilder builder = new SAXBuilder();
	private List<File> listFiles = new FileList();
	private List<File> listDialogFiles = new FileList();

	private static Map<String, Element> pageMap = new HashMap<String, Element>();

	private static Map<String, String> pageHeadJsonMap = new HashMap<String, String>();
	private static Map<String, String> pagestoreFiledJsonMap = new HashMap<String, String>();
	private static Map<String, String> pageHqlMap = new HashMap<String, String>();

	private static Map<String, RightMenu> rightMenuMap = new HashMap<String, RightMenu>();

	private static Map<String, DialogItems> dialogItemsMap = new HashMap<String, DialogItems>();

	private static Map<String, List<PageDataIndex>> dataIndexMap = new HashMap<String, List<PageDataIndex>>();

	private int serialNumber = 0;

	public ExtPageXmlControl() {
		this.extPageDir = XmlContent.getExtPage();
		this.dialogPageDir = XmlContent.getExtDialog();
		this.detailPageDir = XmlContent.getExtDetail();
	}

	public String getRightByUser(List<Power> powers) {
		List<RightMenu> rightMenus = new ArrayList<RightMenu>();
		for (int i = 0; i < powers.size(); ++i) {
			RightMenu menu = getRightMenuById(((Power) powers.get(i))
					.getPowerId());
			rightMenus.add(menu);
		}
		Collections.sort(rightMenus, new RightMenuSort());
		return ExtJsonControl.toJson(rightMenus);
	}

	public RightMenu getRightMenuById(String rightMenuId) {
		if (!(rightMenuMap.containsKey(rightMenuId))) {
			throw new SysException(rightMenuId+ "get menu right null ! plase checked xml");
		}
		return ((RightMenu) rightMenuMap.get(rightMenuId));
	}

	public String getPageHeadToJson(String pageId) {
		if (!(pageHeadJsonMap.containsKey(pageId))) {
			pageHeadJsonMap.put(pageId,
					ExtJsonControl.toJson(getPageHeadToObj(pageId)));
		}
		return ((String) pageHeadJsonMap.get(pageId));
	}

	public List<PageDataIndex> getDataIndexByHql(String pageId) {
		if (!(dataIndexMap.containsKey(pageId))) {
			String hql = getPageHql(pageId);
			hql.toUpperCase();
			String regHql = hql.toUpperCase();
			int startIndex = regHql.indexOf("SELECT");
			int endIndex = regHql.indexOf("FROM");

			if ((startIndex <= -1) || (endIndex <= -1)) {
				throw new SysException("[" + hql + "] 解析语法错误 !");
			}
			startIndex += "SELECT".length();
			List pageStores = new ArrayList();
			String stroeStr = hql.substring(startIndex, endIndex).toString();
			for (String str : stroeStr.split(",")) {
				pageStores.add(new PageDataIndex(str.trim().replaceAll("\\.",
						"_")));
			}
			dataIndexMap.put(pageId, pageStores);
		}
		return ((List) dataIndexMap.get(pageId));
	}

	public String getPageStoreFiled(String pageId) {
		if (!(pagestoreFiledJsonMap.containsKey(pageId))) {
			pagestoreFiledJsonMap.put(pageId, ExtJsonControl
					.toJson(getDataIndexByHql(pageId)));
		}
		return ((String) pagestoreFiledJsonMap.get(pageId));
	}

	public String getPageHql(String pageId) {
		if (!(pageHqlMap.containsKey(pageId))) {
			Element e = getPage(pageId);
			Element headElement = e.getChild("hql");
			pageHqlMap.put(pageId, headElement.getText());
		}
		return ((String) pageHqlMap.get(pageId));
	}
	
	/**
	 * 自定义页面location 不是自定义页面返回NULL
	 * @param pageId
	 * @return
	 */
	public String getCustomPageLocation(String pageId){
		return getPage(pageId).getChildText("location");
	}

	public List<PageXml> getPageHeadToObj(String pageId) {
		Element e = getPage(pageId);
		List<PageXml> xmls = new ArrayList<PageXml>();
		Element headElement = e.getChild("head");
		List<Element> rows = headElement.getChildren("row");
		String renderer = e.getChildText("renderer");
		if (renderer != null) {
			renderer = renderer.trim();
			if (renderer.length() < 1) {
				renderer = null;
			} else {
				renderer = renderer.replaceAll("\n", "");
				renderer = renderer.replaceAll("\t", "");
			}
		}

		List<PageDataIndex> dataIndexs = getDataIndexByHql(pageId);

		PageXml pageXml1 = new PageXml();
		xmls.add(pageXml1);

		for (int i = 0; i < rows.size(); ++i) {
			Element row = (Element) rows.get(i);
			String header = row.getChildText("header");
			String dataIndex = ((PageDataIndex) dataIndexs.get(i)).getName();
			String sortable = row.getChildText("sortable");
			String hidden = row.getChildText("hidden");
			String rendererChildren = row.getChildText("renderer");

			PageXml pageXml = new PageXml();
			pageXml.setHeader(header);
			pageXml.setDataIndex(dataIndex);
			pageXml.setSortable(Boolean.valueOf(sortable).booleanValue());
			pageXml.setHidden(Boolean.valueOf(hidden).booleanValue());

			if (rendererChildren != null) {
				rendererChildren = rendererChildren.trim();
				if (rendererChildren.length() < 1) {
					rendererChildren = null;
				} else {
					rendererChildren = rendererChildren.replaceAll("\n", "");
					rendererChildren = rendererChildren.replaceAll("\t", "");
				}
			}

			if (rendererChildren != null)
				pageXml.setRenderer(rendererChildren);
			else if (renderer != null) {
				pageXml.setRenderer(renderer);
			}

			xmls.add(pageXml);
		}

		Element menusElement = e.getChild("menus");
		List<Element> menuRows = menusElement.getChildren("menu");
		for (int i = 0; i < menuRows.size(); ++i) {
			Element row = (Element) menuRows.get(i);
			String id = row.getChildText("id");
			String type = row.getChildText("type");
			String selectType = row.getChildText("selectType");
			String text = row.getChildText("text");
			String menuPageId = row.getChildText("pageId");
			String action = row.getChildText("action");
			String condition = row.getChildText("condition");
			String confirm = row.getChildText("confirm");
			String sort = row.getChildText("sort");

			RightMenu rightMenu = new RightMenu();
			rightMenu.setMid(id);
			rightMenu.setType(type);
			rightMenu.setSelectType(selectType);
			rightMenu.setText(text);
			rightMenu.setConfirm(confirm);
			rightMenu.setManagerAction(action);
			rightMenu.setPageId(menuPageId);
			
			if(sort !=null ){
				rightMenu.setSort(Integer.parseInt(sort));
			}
			
			if (condition != null) {
				condition = condition.trim();
				if (condition.length() < 1) {
					condition = null;
				} else {
					condition = condition.replaceAll("\n", "");
					condition = condition.replaceAll("\t", "");
				}
			}
			rightMenu.setCondition(condition);
			rightMenuMap.put(id, rightMenu);
			try {
				if (menuPageId != null)
					ExtContent.addDetailPage(menuPageId, id);
			} catch (WebException e1) {
				e1.printStackTrace();
			}
		}
		return xmls;
	}
	
	public String getDialogItemTOJson(String dialogId, List<Object[]> objects) {
		DialogItems items = getDialog(dialogId);
		if (items.getDialogProperties().getDealogType().equals("edit")) {
			List<DialogItem> dialogItems = getDialog(dialogId).getItems();
			if (objects == null) {
				return ExtJsonControl.toJson(dialogItems);
			}

			for (int i = 0; i < objects.size(); i++) {
				for (int j = 0; j < objects.get(i).length; j++) {
					if (objects.get(i)[j] != null) {
						dialogItems.get(j).setValue(objects.get(i)[j].toString());
					}
				}
			}
			return ExtJsonControl.toJson(dialogItems);
		}
		return ExtJsonControl.toJson(items.getDetailXmls());
	}

	public String getDialogPropertiesTOJson(String dialogId) {
		return ExtJsonControl.toJson(getDialog(dialogId).getDialogProperties());
	}

	public String getDialogPropertiesTOJson(DialogProperties properties) {
		return ExtJsonControl.toJson(properties);
	}
	
	public String getCustomTOJson(String dialogId){
		return ExtJsonControl.toJson(getDialog(dialogId).getCustom());
	}

	public DialogProperties getDialogProperties(String dialogId) {
		return getDialog(dialogId).getDialogProperties();
	}

	public String getDialogHql(String dialogId) {
		return getDialog(dialogId).getHql();
	}

	public DialogItems getDialog(String dialogId) {
		
		if (!dialogItemsMap.containsKey(dialogId)) {
			File dialogDir = new File(dialogPageDir);
			
			if (!FileUtil.isExist(dialogDir)) {
				throw new SysException("dialogDir is not Exists ! ["
						+ dialogDir.getAbsolutePath() + "]");
			}

			if (!listDialogFiles.contains(dialogDir)) {
				FileUtil.getFiles(listDialogFiles, dialogDir, "xml");
			}

			for (File file : listDialogFiles) {
				if (!file.getName().equals(dialogId + ".xml")) {
					continue;
				}

				try {
					Element element = saxXml(file);

					DialogItems dialogItems = new DialogItems();

					DialogProperties properties = new DialogProperties();

					Element propertiesElement = element.getChild("properties");

					String width = propertiesElement.getChildText("width");
					String height = propertiesElement.getChildText("height");
					String title = propertiesElement.getChildText("title");
					String isRefresh = propertiesElement
							.getChildText("isRefresh");
					String type = propertiesElement.getChildText("type");

					properties.setWidth(Integer.parseInt(width));
					properties.setHeight(Integer.parseInt(height));
					properties.setTitle(title);
					if (isRefresh != null && isRefresh.trim().length() > 3) {
						properties.setRefresh(Boolean.parseBoolean(isRefresh));
					}

					if (type != null) {
						properties.setDealogType(type);
					}

					dialogItems.setDialogProperties(properties);

					if (properties.getDealogType() != null
							&& properties.getDealogType().equals(PageType.EDIT)) {
						List<Element> items = element.getChild("items")
								.getChildren("item");
						List<DialogItem> list = new ArrayList<DialogItem>();
						for (Element ele : items) {

							String xtype = ele.getChildText("type");
							String label = ele.getChildText("label");
							String name = ele.getChildText("name");
							String required = ele.getChildText("required");
							String emptyText = ele.getChildText("emptyText");
							String value = ele.getChildText("value");
							String requiredMsg = ele
									.getChildText("requiredMsg");
							String hidden = ele.getChildText("hidden");
							String disabled = ele.getChildText("disabled");
							String psw = ele.getChildText("inputType");

							if (xtype.equals("remote")) {
								ExtComboBox comboBox = new ExtComboBox();
								comboBox.setXtype("combo");
								comboBox.setName(name);
								comboBox.setFieldLabel(label);
								comboBox.setBlankText(requiredMsg);

								if (required != null
										&& required.trim().length() > 3) {
									comboBox.setAllowBlank(Boolean
											.parseBoolean(required));
								}

								if (hidden != null
										&& hidden.trim().length() > 3) {
									comboBox.setHidden(Boolean
											.parseBoolean(hidden));
								}
								if (disabled != null
										&& disabled.trim().length() > 3) {
									comboBox.setDisabled(Boolean
											.parseBoolean(disabled));
								}

								serialNumber++;
								if (serialNumber >= Integer.MAX_VALUE) {
									serialNumber = 0;
								}
								String cbId = System.currentTimeMillis() + "."
										+ serialNumber;
								comboBox.setCbId(cbId);
								comboBox.setEmptyText(emptyText);

								try {
									ExtContent.addcomBoxMap(cbId,
											ele.getChildText("hql"));
								} catch (WebException e) {
									e.printStackTrace();
								}

								list.add(comboBox);
							} else if(xtype.equals("upload")){
								ExtUpFileLoad extUpFileLoad = new ExtUpFileLoad();
								extUpFileLoad.setXtype("textfield");
								extUpFileLoad.setEmptyText("点击上传文件");
								extUpFileLoad.setName(name);
								extUpFileLoad.setFieldLabel(label);
								extUpFileLoad.setBlankText(requiredMsg);

								if (required != null
										&& required.trim().length() > 3) {
									extUpFileLoad.setAllowBlank(Boolean
											.parseBoolean(required));
								}

								if (hidden != null
										&& hidden.trim().length() > 3) {
									extUpFileLoad.setHidden(Boolean
											.parseBoolean(hidden));
								}
								if (disabled != null
										&& disabled.trim().length() > 3) {
									extUpFileLoad.setDisabled(Boolean
											.parseBoolean(disabled));
								}
								
								serialNumber++;
								if (serialNumber >= Integer.MAX_VALUE) {
									serialNumber = 0;
								}
//								String cbId = System.currentTimeMillis() + "."
//										+ serialNumber;
//								
//								extUpFileLoad.setId(cbId);
								
								list.add(extUpFileLoad);
							}else {
								DialogItem item = new DialogItem();
								item.setXtype(xtype);
								item.setFieldLabel(label);
								item.setName(name);
								item.setEmptyText(emptyText);
								if(psw!=null){
									item.setInputType(psw);
								}
								if (required != null
										&& required.trim().length() > 3) {
									item.setAllowBlank(Boolean
											.parseBoolean(required));
								}
								item.setBlankText(requiredMsg);
								item.setValue(value);
								if (hidden != null
										&& hidden.trim().length() > 3) {
									item.setHidden(Boolean.parseBoolean(hidden));
								}
								if (disabled != null
										&& disabled.trim().length() > 3) {
									item.setDisabled(Boolean
											.parseBoolean(disabled));
								}

								list.add(item);
							}

						}
						;

						dialogItems.setItems(list);
					} else if (properties.getDealogType() != null
							&& properties.getDealogType().equals(
									PageType.DETAIL)) {

						dialogItems.setDetailXmls(getPageHeadToObj(dialogId));

					}else if (properties.getDealogType() != null
							&& properties.getDealogType().equals(
									PageType.CUSTOM)) {

						PageCustom custom = new PageCustom();
						custom.setLocation(element.getChild("pages").getChildText("location"));
						dialogItems.setCustom(custom);

					}else if (properties.getDealogType() != null) {
						throw new SysException("type error ! ["
								+ properties.getDealogType() + " in "
								+ dialogId + "]");
					}

					dialogItems.setHql(element.getChildText("hql"));

					dialogItemsMap.put(dialogId, dialogItems);

					break;

				} catch (JDOMException e) {
					e.printStackTrace();
				}

			}

		}

		if (!dialogItemsMap.containsKey(dialogId)) {
			throw new SysException("dialog id File is not Exists ! ["
					+ dialogId + "]");
		}
		return dialogItemsMap.get(dialogId);
	}

	public Element getPage(String pageId) {
		if (pageMap.containsKey(pageId)) {
			return ((Element) pageMap.get(pageId));
		}

		File extPageFile = new File(this.extPageDir);
		File detailPageFile = new File(this.detailPageDir);
		
		if (!(this.listFiles.contains(extPageFile))) {
			FileUtil.getFiles(this.listFiles, extPageFile, "xml");
		}
		if(! (this.listFiles.contains(detailPageFile))){
			FileUtil.getFiles(this.listFiles, detailPageFile, "xml");
		}
		
		
		for (File fe : this.listFiles) {
			if (!(fe.getName().equals(pageId + ".xml")))
				continue;
			try {
				Element element = saxXml(fe);
				if (element.getName().equals("pages"))
					pageMap.put(pageId, element);
				else {
					pageMap.put(pageId, element.getChild("pages"));
				}
				return ((Element) pageMap.get(pageId));
			} catch (JDOMException e) {
				e.printStackTrace();
			}

		}

		return null;
	}

	private Element saxXml(File file) throws JDOMException {
		Document doc = this.builder.build(file);
		Element rootElement = doc.getRootElement();
		return rootElement;
	}

	public static Map<String, RightMenu> getRightMenuMap() {
		return rightMenuMap;
	}
}
